package com.xiaoq.order.endpoint;

import com.alibaba.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.xiaoq.BaseEndpoint2B;
import com.xiaoq.apis.sites.IZoneMasterApi;
import com.xiaoq.apis.sites.ZoneMaster4DataStatisVo;
import com.xiaoq.apis.user.IUserApi;
import com.xiaoq.apis.user.UserInfo4OrderTourVo;
import com.xiaoq.apis.user.UserPhone4OrderVo;
import com.xiaoq.coms.GenericDataResponse;
import com.xiaoq.coms.GenericListResponse;
import com.xiaoq.coms.GenericResponse;
import com.xiaoq.order.entity.OrderTourPipe;
import com.xiaoq.order.entity.ShopOrderCardEntity;
import com.xiaoq.order.service.IShopOrderCardService;
import com.xiaoq.order.service.IShopOrderService;
import com.xiaoq.order.vo.DataStatisticsVo;
import com.xiaoq.order.vo.OrderTourPipeQueryVo;
import io.swagger.annotations.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = "/api/v1/orders_statis")
@Api(tags = "B 端 数据分析")
class DataStatisticsEndpoint2B extends BaseEndpoint2B{


    private static final class DataStatisticsResponse extends GenericListResponse<DataStatisticsVo> {}
    private static final class DeviceStatisticsResponse extends GenericListResponse<DeviceStatisResultVo> {}
    private static final class GenderStatisticsResponse extends GenericDataResponse<GenderStatisVo> {}
    private static final class AgeStatisticsListResponse extends GenericListResponse<AgeStatisVo> {}

    @Autowired
    private IShopOrderService shopOrderService;

    @Reference(interfaceClass=IUserApi.class, check=false, version="1.0.0")
    private IUserApi userDubboApi;

    @Reference(interfaceClass=IZoneMasterApi.class, check=false, version="1.0.0")
    private IZoneMasterApi zoneMasterApi;

    @Autowired
    private ResourceLoader resourceLoader;

    @Autowired
    private IShopOrderCardService shopOrderCardService;


    @ApiOperation(value="游客来源接口", notes="游客来源接口")
    @ApiResponses({
            @ApiResponse(code = 200, response = DataStatisticsResponse.class, message = "游客来源接口")
    })
    @GetMapping(value = "/tours", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> touristList(
            HttpServletRequest request,
            @ApiParam(required = false, name = "startTime", value = "开始时间(yyyy-MM-dd)")
            @RequestParam(required = false)  String startTime,
            @ApiParam(required = false, name = "endTime", value = "结束时间(yyyy-MM-dd)")
            @RequestParam(required = false)  String endTime) {

        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd");
        Long startOrderTimeLong = null;
        Long endOrderTimeLong = null;
        if(StringUtils.isNotBlank(startTime)){
            try {
                startOrderTimeLong = DateTime.parse(startTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("预订时间格式不对");
            }
        }
        if(StringUtils.isNotBlank(endTime)){
            try {
                endOrderTimeLong = DateTime.parse(endTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("预订结束格式不对");
            }
        }

        OrderTourPipeQueryVo pipeQueryVo = new OrderTourPipeQueryVo();
        pipeQueryVo.setShopId(getShopId());
        pipeQueryVo.setStartTime(startOrderTimeLong);
        pipeQueryVo.setEndTime(endOrderTimeLong);
        List<OrderTourPipe> orderTourPipes = shopOrderService.getShopAllOrders4Tour(pipeQueryVo, null);

        Map<String, Integer> userId2OrderCountMap = new HashMap<>();
        List<String> userIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(orderTourPipes)){
            for(OrderTourPipe orderTourPipe : orderTourPipes){
                userId2OrderCountMap.put(orderTourPipe.getUserId(), orderTourPipe.getOrderCount());
                userIdList.add(orderTourPipe.getUserId());
            }
        }

        Map<String, Integer> areaCode2OrderCountMap = new HashMap<>();
        List<String> areaCodeList = new ArrayList<>();
        List<UserPhone4OrderVo> userPhone4OrderVoList = userDubboApi.getUserPhone4OrderTourByUserIds(userIdList);
        if(CollectionUtils.isNotEmpty(userPhone4OrderVoList)) {
            for (UserPhone4OrderVo userPhone4OrderVo : userPhone4OrderVoList){

                String areaCode = userPhone4OrderVo.getAreaCode();
                String userId = userPhone4OrderVo.getUserId();
                Integer orderCount = userId2OrderCountMap.get(userId);
                Integer areaCode2OrderCount = areaCode2OrderCountMap.get(areaCode);
                areaCodeList.add(userPhone4OrderVo.getAreaCode());

                if(orderCount != null){
                    if(areaCode2OrderCount == null){
                        areaCode2OrderCountMap.put(areaCode, orderCount);
                    }else {
                        areaCode2OrderCountMap.put(areaCode, orderCount + areaCode2OrderCount);
                    }
                    //areaCode2OrderCountMap.merge(areaCode, orderCount, (a,b) -> a+b);
                }
            }
        }

        List<ZoneMaster4DataStatisVo> zoneMaster4DataStatisVoList = zoneMasterApi.getZoneMasterListByAreaCode(areaCodeList);

        List<DataStatisticsVo> resultList = new ArrayList<>();
        DataStatisticsVo dataStatisticsVo;
        if(CollectionUtils.isNotEmpty(zoneMaster4DataStatisVoList)){
            for (ZoneMaster4DataStatisVo zoneMaster4DataStatisVo : zoneMaster4DataStatisVoList){

                Integer orderCount = areaCode2OrderCountMap.get(zoneMaster4DataStatisVo.getAreaCode());

                if(orderCount != null){
                    dataStatisticsVo = new DataStatisticsVo();

                    dataStatisticsVo.setCityName(zoneMaster4DataStatisVo.getName());
                    dataStatisticsVo.setLatitude(zoneMaster4DataStatisVo.getLatitude());
                    dataStatisticsVo.setLongitude(zoneMaster4DataStatisVo.getLongitude());
                    dataStatisticsVo.setOrderCount(orderCount);

                    resultList.add(dataStatisticsVo);
                }
            }
        }

        return DataStatisticsResponse.listNoCount(resultList);
    }

    @ApiOperation(value="游客性别统计", notes="游客性别统计")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenderStatisticsResponse.class, message = "游客性别统计")
    })
    @GetMapping(value = "/genderstatis", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> genderStatis(HttpServletRequest request,
                                          @ApiParam(required = false, name = "minCreatedTime", value = "开始时间(yyyy-MM-dd)")
                                          @RequestParam(required = false)  String minCreatedTime,
                                          @ApiParam(required = false, name = "maxCreatedTime", value = "结束时间(yyyy-MM-dd)")
                                              @RequestParam(required = false)  String maxCreatedTime) {

        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd");
        Long minCreatedTimeLong = null;
        Long maxCreatedTimeLong = null;
        if(StringUtils.isNotBlank(minCreatedTime)){
            try {
                minCreatedTimeLong = DateTime.parse(minCreatedTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("开始时间格式不对");
            }
        }
        if(StringUtils.isNotBlank(maxCreatedTime)){
            try {
                maxCreatedTimeLong = DateTime.parse(maxCreatedTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("结束时间格式不对");
            }
        }

        String shopId = getShopId();
        GenderStatisVo genderStatisVo = new GenderStatisVo();
        List<ShopOrderCardEntity> shopOrderCardList = shopOrderCardService.getListByOrderIdList(shopId, null, minCreatedTimeLong, maxCreatedTimeLong);
        int female = 0;
        int male = 0;
        if(CollectionUtils.isNotEmpty(shopOrderCardList)){
            for (ShopOrderCardEntity cardEntity : shopOrderCardList){
                int gender = cardEntity.getGender();
                if(gender == 0){
                    female++;
                }else {
                    male++;
                }
            }
            genderStatisVo.setMaleNum(male);
            genderStatisVo.setFemaleNum(female);
        }else {

            //测试的假数据
            female = 15 + (int)(Math.random() * 60) ;
            genderStatisVo.setFemaleNum(female);
            genderStatisVo.setMaleNum(100-female);
        }

        return GenderStatisticsResponse.okWithData(genderStatisVo);
    }


    @ApiOperation(value="年龄统计", notes="年龄统计")
    @ApiResponses({
            @ApiResponse(code = 200, response = AgeStatisticsListResponse.class, message = "年龄统计")
    })
    @GetMapping(value = "/agestatis", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> ageStatis(HttpServletRequest request,
                                       @ApiParam(required = false, name = "minCreatedTime", value = "开始时间(yyyy-MM-dd)")
                                        @RequestParam(required = false)  String minCreatedTime,
                                       @ApiParam(required = false, name = "maxCreatedTime", value = "结束时间(yyyy-MM-dd)")
                                           @RequestParam(required = false)  String maxCreatedTime) {

        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd");
        Long minCreatedTimeLong = null;
        Long maxCreatedTimeLong = null;
        if(StringUtils.isNotBlank(minCreatedTime)){
            try {
                minCreatedTimeLong = DateTime.parse(minCreatedTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("开始时间格式不对");
            }
        }
        if(StringUtils.isNotBlank(maxCreatedTime)){
            try {
                maxCreatedTimeLong = DateTime.parse(maxCreatedTime, format).getMillis();
            }catch (Exception e){
                return GenericResponse.ng("结束时间格式不对");
            }
        }

        String shopId = getShopId();
        List<ShopOrderCardEntity> shopOrderCardList = shopOrderCardService.getListByOrderIdList(shopId, null, minCreatedTimeLong, maxCreatedTimeLong);
        int maxAge19 = 0;
        int maxAge29 = 0;
        int maxAge39 = 0;
        int maxAge49 = 0;
        int maxAge59 = 0;
        int maxAgeOther = 0;
        if (CollectionUtils.isNotEmpty(shopOrderCardList)){
            for (ShopOrderCardEntity cardEntity : shopOrderCardList){
                int commitOrderAge = cardEntity.getCommitOrderAge();

                if(commitOrderAge <= 19){
                    maxAge19 ++;
                }else if(commitOrderAge <= 29){
                    maxAge29 ++;
                }else if(commitOrderAge <= 39){
                    maxAge39 ++;
                }else if(commitOrderAge <= 49){
                    maxAge49 ++;
                }else if(commitOrderAge <= 59){
                    maxAge59 ++;
                }else {
                    maxAgeOther ++;
                }
            }
        }else{
            maxAge19 = 30;
            maxAge29 = 80;
            maxAge39 = 40;
            maxAge49 = 30;
            maxAge59 = 20;
            maxAgeOther = 33;
        }

        List<AgeStatisVo> resultList = Arrays.asList(
                new AgeStatisVo(1,"10-19岁", maxAge19),
                new AgeStatisVo(2,"20-29岁", maxAge29),
                new AgeStatisVo(3,"30-39岁", maxAge39),
                new AgeStatisVo(4,"40-49岁", maxAge49),
                new AgeStatisVo(5,"50-59岁", maxAge59),
                new AgeStatisVo(6,"其他", maxAgeOther));

        return AgeStatisticsListResponse.listNoCount(resultList);
    }



    @ApiOperation(value="游客登录类型统计", notes="游客登录类型统计")
    @ApiResponses({
            @ApiResponse(code = 200, response = DeviceStatisticsResponse.class, message = "游客登录类型统计")
    })
    @GetMapping(value = "/loginstatis", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> loginstatis(
            HttpServletRequest request) {

        //可写static块读取文件
        Resource bandsResource = resourceLoader.getResource("classpath:\\static\\androidDevice.txt");
        List<String> allVersionList = null;
        try {
            allVersionList = IOUtils.readLines(bandsResource.getInputStream(), "utf-8");
            System.out.println("allVersionList size: ******* " + allVersionList.size());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("android手机品牌不存在! ");
        }

        if(CollectionUtils.isEmpty(allVersionList)){
            return GenericResponse.ng("手机型号字典不存在");
        }

        Map<String, String> version2BandMap = new HashMap<>();
        for (String line : allVersionList){
            String[] bands = StringUtils.split(line, ":");
            String bandName = bands[0];
            String[] verions = StringUtils.split(bands[1], ",");
            for (String version : verions){
                if(StringUtils.isNotEmpty(version)){
                    version2BandMap.put(version, bandName);
                }
            }
        }

        OrderTourPipeQueryVo pipeQueryVo = new OrderTourPipeQueryVo();
        pipeQueryVo.setShopId(getShopId());

        List<OrderTourPipe> orderTourPipes = shopOrderService.getShopAllOrders4Tour(pipeQueryVo, null);

        List<String> userIdList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(orderTourPipes)){
            for (OrderTourPipe orderTourPipe : orderTourPipes){
                userIdList.add(orderTourPipe.getUserId());
            }
        }

        List<UserInfo4OrderTourVo> userInfo4OrderTourList = userDubboApi.getUserInfo4OrderTourByUserIds(userIdList);

        Map<String, Integer> bandName2CountMap = new HashMap<>();

        Map<String, List<DeviceVo>> bandName2DeviceListMap = new HashMap<>();

        Map<String, List<UserInfo4OrderTourVo>> version2ListMap = null;

        List<UserInfo4OrderTourVo> iosUserInfoList = new ArrayList<>();
        List<UserInfo4OrderTourVo> androidUserInfoList = new ArrayList<>();

        if(CollectionUtils.isNotEmpty(userInfo4OrderTourList)){

            for (UserInfo4OrderTourVo userInfo4OrderTourVo : userInfo4OrderTourList){
                if (StringUtils.equalsIgnoreCase("iOS", userInfo4OrderTourVo.getOsType())){
                    iosUserInfoList.add(userInfo4OrderTourVo);
                }else if (StringUtils.equalsIgnoreCase("Android", userInfo4OrderTourVo.getOsType())){
                    androidUserInfoList.add(userInfo4OrderTourVo);
                }
            }

            version2ListMap = androidUserInfoList.parallelStream().collect(Collectors.groupingBy(UserInfo4OrderTourVo::getMobileMode));
        }

        if(version2ListMap == null) {
            version2ListMap = new HashMap<>();
        }

        for (Map.Entry<String, List<UserInfo4OrderTourVo>> entry : version2ListMap.entrySet()){
            String version = entry.getKey();
            List<UserInfo4OrderTourVo> userInfo4OrderTourVos = entry.getValue();
            String bandName = version2BandMap.get(version);

            if(StringUtils.isNotEmpty(bandName) && CollectionUtils.isNotEmpty(userInfo4OrderTourVos)){
                int size = userInfo4OrderTourVos.size();
                bandName2DeviceListMap.merge(bandName, new ArrayList<>(), (value, newValue) -> value).add(new DeviceVo(version,size));
                bandName2CountMap.merge(bandName, size, (value, newValue)-> value + newValue);
            }
        }

        //有序的倒排
        Map<String, Integer> bandName2CountSortedMap = new LinkedHashMap<>();
        bandName2CountMap.entrySet().stream()
                .sorted(Map.Entry.<String, Integer> comparingByValue().reversed())
                .forEachOrdered(x -> bandName2CountSortedMap.put(x.getKey(), x.getValue()));

        List<DeviceStatisResultVo> resultList = new ArrayList<>();
        DeviceStatisResultVo deviceStatisResultVo;
        DeviceStatisVo deviceStatisVo;
        List<DeviceStatisVo> bandDeviceStaticVo = new ArrayList<>();
        List<DeviceStatisVo> modelDeviceStaticVo = new ArrayList<>();
        List<DeviceStatisVo> iOSDeviceStaticVo = new ArrayList<>();

        //处理android band
        int i = 0;
        for (Map.Entry<String, Integer> entry : bandName2CountSortedMap.entrySet()){
            String bandName  = entry.getKey();
            Integer bandVersionCount = entry.getValue();

            //处理model
            List<DeviceVo> deviceVos = bandName2DeviceListMap.get(bandName);
            if(CollectionUtils.isNotEmpty(deviceVos)){

                Collections.sort(deviceVos, (o1, o2) -> o2.getCount()-o1.getCount());
                DeviceVo deviceVo = deviceVos.get(0);
                DeviceStatisVo tmpDeviceStaticVO = new DeviceStatisVo();
                tmpDeviceStaticVO.setBrandName(deviceVo.getVersion());
                tmpDeviceStaticVO.setNumber(deviceVo.getCount());
                tmpDeviceStaticVO.setSortIndex(i);
                modelDeviceStaticVo.add(tmpDeviceStaticVO);

                //处理其他
                tmpDeviceStaticVO = new DeviceStatisVo();
                tmpDeviceStaticVO.setBrandName("其他");
                tmpDeviceStaticVO.setNumber(bandVersionCount - deviceVo.getCount());
                tmpDeviceStaticVO.setSortIndex(i);
                modelDeviceStaticVo.add(tmpDeviceStaticVO);
            }

            deviceStatisVo = new DeviceStatisVo();
            deviceStatisVo.setBrandName(bandName);
            deviceStatisVo.setNumber(bandVersionCount);
            deviceStatisVo.setSortIndex(i++);
            bandDeviceStaticVo.add(deviceStatisVo);

            if(i == 3){
                break;
            }
        }

        //iosUserInfoList
        Map<String, Integer> iosType2CountMap = iosUserInfoList.parallelStream()
                .collect(Collectors.groupingBy(UserInfo4OrderTourVo::getMobileMode, Collectors.summingInt(p -> 1)));

        for (Map.Entry<String, Integer> entry : iosType2CountMap.entrySet()){
            DeviceStatisVo tmpDeviceStaticVO = new DeviceStatisVo();
            tmpDeviceStaticVO.setBrandName(entry.getKey());
            tmpDeviceStaticVO.setNumber(entry.getValue());
            tmpDeviceStaticVO.setSortIndex(entry.getValue());
            iOSDeviceStaticVo.add(tmpDeviceStaticVO);
        }
        deviceStatisResultVo = new DeviceStatisResultVo();
        deviceStatisResultVo.setBrandName("iOS");
        deviceStatisResultVo.setDeviceList(iOSDeviceStaticVo);
        resultList.add(deviceStatisResultVo);

        //处理band
        deviceStatisResultVo = new DeviceStatisResultVo();
        deviceStatisResultVo.setBrandName("brand");
        deviceStatisResultVo.setDeviceList(bandDeviceStaticVo);
        resultList.add(deviceStatisResultVo);
        //处理 android model
        deviceStatisResultVo = new DeviceStatisResultVo();
        deviceStatisResultVo.setBrandName("model");
        deviceStatisResultVo.setDeviceList(modelDeviceStaticVo);
        resultList.add(deviceStatisResultVo);

        return DeviceStatisticsResponse.listNoCount(resultList);
    }

    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class DeviceStatisResultVo {
        @ApiModelProperty(name = "brandName", value = "品牌名称", position = 10)
        private String brandName;
        @ApiModelProperty(name = "deviceList", value = "设备集合", position = 20)
        private List<DeviceStatisVo> deviceList;

        public String getBrandName() {
            return brandName;
        }

        public void setBrandName(String brandName) {
            this.brandName = brandName;
        }

        public List<DeviceStatisVo> getDeviceList() {
            return deviceList;
        }

        public void setDeviceList(List<DeviceStatisVo> deviceList) {
            this.deviceList = deviceList;
        }
    }

    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class DeviceStatisVo {
        @ApiModelProperty(name = "brandName", value = "型号名称", position = 10)
        private String brandName; //品牌名称
        @ApiModelProperty(name = "number", value = "数量", position = 20)
        private int number;
        @ApiModelProperty(name = "sortIndex", value = "排序顺序", position = 30)
        private int sortIndex;

        public String getBrandName() {
            return brandName;
        }

        public void setBrandName(String brandName) {
            this.brandName = brandName;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        public int getSortIndex() {
            return sortIndex;
        }

        public void setSortIndex(int sortIndex) {
            this.sortIndex = sortIndex;
        }
    }


    public static class GenderStatisVo {
        @ApiModelProperty(name = "maleNum", value = "男性数量", position = 10)
        private int maleNum;
        @ApiModelProperty(name = "female", value = "女性数量", position = 20)
        private int femaleNum;

        public int getMaleNum() {
            return maleNum;
        }

        public void setMaleNum(int maleNum) {
            this.maleNum = maleNum;
        }

        public int getFemaleNum() {
            return femaleNum;
        }

        public void setFemaleNum(int femaleNum) {
            this.femaleNum = femaleNum;
        }
    }

    private static class DeviceVo {

        private String version;
        private int count;

        public DeviceVo(String version, int count) {
            this.version = version;
            this.count = count;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }

    }

    public static class AgeStatisVo {
        @ApiModelProperty(name = "id", value = "序号", position = 10)
        private int id;
        @ApiModelProperty(name = "ageRange", value = "0到19，20到29，30到39，40到49，50到59，60其他", position = 10)
        private String ageRange;
        @ApiModelProperty(name = "count", value = "数量", position = 20)
        private int count;

        public AgeStatisVo() {
        }

        public AgeStatisVo(int id, String ageRange, int count) {
            this.id = id;
            this.ageRange = ageRange;
            this.count = count;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getAgeRange() {
            return ageRange;
        }

        public void setAgeRange(String ageRange) {
            this.ageRange = ageRange;
        }

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }
    }


}


























